package img

import (
	"image"
	"image/jpeg"
	"os"
	"encoding/binary"
	"bytes"
	"image/png"
	"strings"
)

func ReadImage(data, lut []byte, photometric string, samplePerPixel, rows, columns, ww, wl int, isBigEndian bool) image.Image {
	var m image.Image
	if photometric == "RGB" && samplePerPixel == 3 {
		m = readRGB(data, rows, columns, 0, 0)
	} else if photometric == "MONOCHROME2" {
		m = readGray(data, rows, columns, ww, wl, isBigEndian)
	}
	return m
}

func readRGB(data []byte, rows, columns, ww, wl int) image.Image {
	m := image.NewNRGBA(image.Rect(0, 0, columns, rows))
	k, l := 0, 0
	for i := 0; i < columns; i++ {
		for j := 0; j < rows; j++ {
			m.Pix[l] = data[k]
			m.Pix[l+1] = data[k+1]
			m.Pix[l+2] = data[k+2]
			m.Pix[l+3] = 255
			k += 3
			l += 4
		}
	}
	return m
}

func readGray(data []byte, rows, columns, ww, wl int, isBigEndian bool) image.Image {
	m := image.NewGray(image.Rect(0, 0, columns, rows))
	k, l := 0, 0
	lut := createLUT(ww, wl)
	for i := 0; i < columns; i++ {
		for j := 0; j < rows; j++ {
			var pix int16
			b := bytes.NewReader(data[l:l+2])
			if isBigEndian {
				binary.Read(b, binary.BigEndian, &pix)
			} else {
				binary.Read(b, binary.LittleEndian, &pix)
			}
			pixel := int(pix)
			m.Pix[k] = lut[pixel]
			k++
			l += 2
		}
	}
	return m
}

func createLUT(ww, wl int) []byte {
	wMax := float64(wl + ww/2)
	wMin := float64(wl - ww/2)
	bytes := make([]byte, 65536)
	for i := 0; i < 65536; i++ {
		pixel := float64(i)
		val := (pixel - wMin) / (wMax - wMin) * 255
		if val < 0 {
			bytes[i] = 0
		} else if val > 255 {
			bytes[i] = 255
		} else {
			bytes[i] = uint8(val)
		}
	}
	return bytes
}

func SaveAs(file *os.File, img image.Image) error {
	if strings.HasSuffix(file.Name(), ".jpg") || strings.HasSuffix(file.Name(), ".jpeg") {
		return jpeg.Encode(file, img, nil)
	} else if strings.HasSuffix(file.Name(), ".png") {
		return png.Encode(file, img)
	} else {
		return png.Encode(file, img)
	}
}
